package com.imi.sdk.jnitest

import android.app.Fragment
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewManager
import android.widget.TextView
import com.hjimi.api.iminect.ImiFrameType
import com.imi.sdk.render.RenderScreen
import org.jetbrains.anko.*
import org.jetbrains.anko.internals.AnkoInternals
import kotlin.concurrent.thread

class CameraPreviewFragment : Fragment() {

    companion object {
        val W = 640
        val H = 480
    }

    override fun onStop() {
        camera?.release()
        super.onStop()
    }

    var testId:Int = 0

    val master by lazy {
        activity as? MainActivity
    }

    inline fun <reified T: View> ViewManager.ankoView(factory:(ctx: Context)->T, init:T.()->Unit={}):T {
        val cc = AnkoInternals.wrapContextIfNeeded(ctx = AnkoInternals.getContext(this),theme = 0)
        val v = factory(cc)
        init(v)
        AnkoInternals.addView(this,v)
        return v
    }

    var showRgbPreview2=false

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View = UI{
        verticalLayout {

            textView("${master?.getTestName(testId)}")

            val w = 640
            val h = 480

            linearLayout {
                verticalLayout {
                    frameLayout {
                        lparams(w, w)

                        ankoView(::RenderScreen) {
                            screen = this
                            onScreenReady(this)
                        }

                        //ankoView(::MyView)

                    }
                    frameLayout {
                        lparams(w, h)

                        ankoView(::RenderScreen) {
                            screenD = this
                            onScreenReadyD(this)
                        }

                        //ankoView(::MyView)
                    }

                    frameLayout {
                        lparams(w, h)

                        ankoView(::RenderScreen) {
                            screenO = this
                            onScreenReadyO(this)
                        }

                        //ankoView(::MyView)
                    }
                }

                verticalLayout {

                    checkBox("Rgb in preview 2") {
                        setOnCheckedChangeListener { v, isChecked ->
                            showRgbPreview2 = isChecked
                        }
                    }

                    button("Start"){
                        setOnClickListener { startTest() }
                    }
                    button("Stop"){
                        setOnClickListener { stopTest() }
                    }

                    scrollView {
                        verticalLayout {
                            textView(">>") {
                                txtInfo = this
                            }
                        }.lparams(matchParent, wrapContent)
                    }.lparams(matchParent, wrapContent,1f)
                }
            }

//            linearLayout {
////                button("Prepare"){
////                    setOnClickListener { prepareTest() }
////                }
//
//            }


        }
    }.view

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        //camera.initWithCamera()
        prepareTest()
    }

    var screen:RenderScreen? = null
    var screenD:RenderScreen? = null
    var screenO:RenderScreen? = null

    val textureRgb = TextureRenderable1(W,H).apply {
        onDraw = {tid ->
            updateTexture(tid,0)
        }
    }
    fun onScreenReady(rs:RenderScreen){
        rs.addRenderable(textureRgb)
    }

    val textureDep = TextureRenderable1(W,H).apply {
        onDraw = { tid ->
            if(showRgbPreview2){
                updateTexture(tid,5)
            }else{
                updateTexture(tid,1)
            }
        }
    }

    val textureOut = TextureRenderable1(W,H).apply {
        onDraw = {tid ->
            updateTexture(tid,2)
        }
    }

    fun onScreenReadyD(rs:RenderScreen){
        rs.addRenderable(textureDep)
    }

    fun onScreenReadyO(rs:RenderScreen){
        rs.addRenderable(textureOut)
    }

    val camera:Camera by lazy {
        Camera(activity,W,H).apply {
            //depType = ImiFrameType.USER_INDEX_SKELETON
            onEvent = { ev,msg->
                if(ev!=0){
                    updateText(text = "Camera ready")
                }else{
                    updateText(text = "Camera Fail: $msg")
                }
            }
        }
    }


    var txtInfo:TextView? = null

    fun updateText(t:Int=0,text:String){
        runOnUiThread {
            txtInfo?.apply {
                if(lineCount>20 || t == 1){
                    this.text=""
                }
                append("\n${text}")
            }
        }
    }

    fun prepareTest(){



        camera?.depType = ImiFrameType.DEPTH
//                when(getEnv("DepFrameType")){
//            "1"->ImiFrameType.USER_INDEX_SKELETON
//            else -> ImiFrameType.DEPTH
//        }

        camera?.initWithCamera()

    }

    fun clearTest(){


    }


    fun startTest(){
        if(isRunning){
            return
        }

        if(true){
            thread(name="test",start=true) {
                isRunning = true

                val ok = initTest(testId)
                //
                camera?.bindHandle()

                updateText(text="initTest ${ok}")

                if(ok) {

                    val pp = if (getFps() > 0) 1000L / getFps() else 33L
                    //
                    while (isRunning) {
                        val r = stepTest(testId)
                        if (!r) {
                            break
                        }

                        //
                        screen?.requestRender()
                        screenD?.requestRender()
                        screenO?.requestRender()

                        Thread.sleep(pp)
                    }

                    endTest(testId)
                }
                //
                isRunning = false

                updateText(text="Stopped")
            }
        }
    }

    private var isRunning = false
    fun stopTest(){
        isRunning = false
    }


    external fun initTest(i:Int):Boolean
    external fun stepTest(i:Int):Boolean
    external fun endTest(i:Int):Int
    external fun getEnv(key:String):String?

    external fun getFps():Int

    external fun updateTexture(tid:Int,chan:Int)

    fun print(type:Int, text:String):Int{
        updateText(type,"${text}")
        return 1
    }

    override fun onPause() {
        stopTest()

        clearTest()

        super.onPause()
    }

}
